home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 425_01 / tar / tape.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-02  |  15.5 KB  |  647 lines

  1. /* tape.c - handle (tape) archive for the Tar program (see file tar.c)
  2.  * Author: T.V.Shaporev
  3.  * Creation date: 14 Dec 1990
  4.  * Contains both MS-DOS and UNIX specific codes
  5.  * Called by many functions - see files tar.c store.c extract.c
  6.  */
  7. #include <stdio.h>
  8. #include <errno.h>
  9.  
  10. #include "sysup.h"
  11. #include "modern.h"
  12. #include "zippipe.h"
  13. #include "lzwhead.h"
  14. #include "compress.h"
  15. #include "define.h"
  16.  
  17. #ifdef MODERN
  18. #    include <string.h>
  19. #    include <stdlib.h>
  20. #else
  21. #    ifdef M_XENIX
  22. #        include <string.h>
  23. #    else
  24.         int strlen();
  25.         char *strcpy(), *strncpy(), *mktemp();
  26. #    endif
  27.     extern char *sys_errlist[];
  28.     extern int sys_nerr;
  29. #endif
  30. #ifdef MSDOS
  31. #    include <io.h>
  32. #    ifdef __TURBOC__
  33. #        include <dir.h>
  34. #    else
  35. #        include <direct.h>
  36. #    endif
  37. #else
  38.     int  creat(), open(), read(), write(), close();
  39.     long lseek();
  40. #endif
  41.  
  42. static int n_read, mblock, nblock, rblock, wblock;
  43. static int indread, indwrite;
  44. static char rerror[] = "Tar: tape read error\n";
  45.  
  46. static int  sread  __ARGS__((char*, int));
  47. static int  swrite __ARGS__((char*, int));
  48. static int  sback  __ARGS__((int));
  49. #ifdef MSDOS
  50. extern int  dread  __ARGS__((char*, int));
  51. extern int  dwrite __ARGS__((char*, int));
  52. extern int  dback  __ARGS__((int));
  53.  
  54. extern int  qparse __ARGS__((char*));
  55. extern int  qbegin __ARGS__((void));
  56. extern int  qread  __ARGS__((char*, int));
  57. extern int  qwrite __ARGS__((char*, int));
  58. extern int  qback  __ARGS__((int));
  59. #endif
  60. static void talign __ARGS__((long));
  61.  
  62. void printbs __ARGS__((int));
  63.  
  64. static void psyserr __ARGS__((void))
  65. {
  66.    if (errno < sys_nerr) (void)fprintf(myout, "%s\n", sys_errlist[errno]);
  67.    else                  (void)fprintf(myout, "error %d\n", errno);
  68. }
  69.  
  70. static int sread(buf, n) /* regular file reading */
  71. char *buf; register n;
  72. {
  73.    if ((n = read(handle, buf, n)) == -1) {
  74.       (void)fprintf(myout, "Tar: archive read error: "); psyserr();
  75.    }
  76.    return n;
  77. }
  78.  
  79. static int swrite(buf, n) /* regular file writing */
  80. char *buf; register n;
  81. {
  82.    if (write(hwrite, buf, n) != n) {
  83.       (void)fprintf(myout, "Tar: archive write error: ");
  84. #ifdef MSDOS
  85.       if (n != -1) (void)fprintf(myout,"disk full\n"); else
  86. #endif
  87.       psyserr();
  88.       n = -1;
  89.    }
  90.    return n;
  91. }
  92.  
  93. static int sback(n)
  94. register n;
  95. {
  96.    return lseek(handle, (long)-BLKSIZE*n, 1) < 0 ? -1 : n;
  97. }
  98.  
  99. #ifdef USE_COMPRESS
  100. static int zwrite __ARGS__((char*, int));
  101.  
  102. static int zwrite(buf, n) /* compressed file writing */
  103. char *buf; register n;
  104. {
  105.    cpiece(buf, n); return n;
  106. }
  107. #endif
  108.  
  109. static int gread  __ARGS__((char*, int));
  110. static int gwrite __ARGS__((char*, int));
  111.  
  112. static int gread(buf, n) /* deflated file reading */
  113. char *buf; register n;
  114. {
  115.    if ((n = unzread(buf, n)) == -1) {
  116.       (void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
  117.    }
  118.    return n;
  119. }
  120.  
  121. static int gwrite(buf, n) /* deflated file reading */
  122. char *buf; register n;
  123. {
  124.    if ((n = zipwrite(buf, n)) == -1) {
  125.       (void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
  126.    }
  127.    return n;
  128. }
  129.  
  130. static int ziperr __ARGS__((void))
  131. {
  132.    (void)fprintf(stderr, "Tar: zip error: %s\n", ziperrlist[ziperror]);
  133.    return ziperror == ZNOMEM ? ESMALL : ERINIT;
  134. }
  135.  
  136. #ifndef USE_COMPRESS
  137. static int twofault __ARGS__((char*, int));
  138.  
  139. /*ARGSUSED2*/ static int twofault(buf, n)
  140. char *buf; register n;
  141. {
  142. #ifdef __TURBOC__
  143.    (void)buf; (void)n;
  144. #endif
  145.    return -1;
  146. }
  147. #endif
  148.  
  149. /*ARGSUSED*/ static int onefault(n)
  150. int n;
  151. {
  152. #ifdef __TURBOC__
  153.    (void)n;
  154. #endif
  155.    return -1;
  156. }
  157.  
  158. static int (*pread) __ARGS__((char*, int)) = sread;
  159. static int (*pwrite)__ARGS__((char*, int)) = swrite;
  160. static int (*pback) __ARGS__((int))        = sback;
  161.  
  162. static int (*lread) __ARGS__((char*, int)) = sread;
  163. static int (*lwrite)__ARGS__((char*, int)) = swrite;
  164. static int (*lback) __ARGS__((int))        = sback;
  165. static int (*rcount)__ARGS__((char*, int)) = sread;
  166.  
  167. static int cntread  __ARGS__((char*, int));
  168.  
  169. int cntread(buf, n)
  170. char *buf; register n;
  171. {
  172.    if ((n = (*rcount)(buf, n)) != -1) {
  173.       allblock += (BLKSIZE-1 + (unsigned)n) / BLKSIZE;
  174.    }
  175.    return n;
  176. }
  177.  
  178. static void talign(i)
  179. long i;
  180. {
  181.    if (i % BLKSIZE) {
  182.       (void)fprintf(myout, "Tar: tape blocksize error\n");
  183.       if (!i_flag) done(ERREAD);
  184.    }
  185. }
  186.  
  187. void printbs(bs)
  188. int bs;
  189. {
  190.    if (v_flag) (void)fprintf(myout, "Tar: blocksize = %d\n", bs);
  191. }
  192.  
  193. static void wrerror __ARGS__((void))
  194. {
  195.    (void)fprintf(myout, "Tar: tape write error\n");
  196.    done(EWRITE);
  197. }
  198.  
  199. static int indget;
  200. static int eof_already = FALSE;
  201. static int got_length;
  202. static int indput;
  203.  
  204. static int getbyte __ARGS__(( void ))
  205. {
  206.    if (eof_already) goto end;
  207.    if (indget >= got_length) {
  208.       if (pksize == 0) {
  209.          if ((got_length = (*lread)(pk_inp, MAXBLOCK*BLKSIZE)) < 0) goto err;
  210.          if ((sa.st_mode & S_IFMT) == S_IFCHR) talign((long)got_length);
  211.          pksize = got_length;
  212.          if ((pksize % BLKSIZE) == 0) printbs(pksize/BLKSIZE);
  213.       } else {
  214.          if (got_length < pksize || got_length % BLKSIZE) goto end;
  215.          if ((got_length = (*lread)(pk_inp, pksize)) < 0) goto err;
  216.       }
  217.       if (got_length < 1) goto end;
  218.       indget = 0;
  219.    }
  220.    return ((unsigned char *)pk_inp)[indget++];
  221. err:
  222.    (void)fprintf(myout, rerror);
  223.    done(ERREAD);
  224. end:
  225.    eof_already = TRUE;
  226.    return EOF;
  227. }
  228.  
  229. static void pkflush __ARGS__((void))
  230. {
  231. #ifdef MSDOS
  232.    if (devtype != DEV_FILE && devtype != DEV_FLOP)
  233. #else
  234.    if (!isfile)
  235. #endif
  236.       while (indput < pksize) pk_out[indput++] = 0;
  237.  
  238.    if ((*lwrite)(pk_out, indput) < indput) wrerror();
  239.    indput = 0;
  240. }
  241.  
  242. static void putbyte(c)
  243. register c;
  244. {
  245.    if (indput >= pksize) {
  246. #ifndef pksize
  247.       /* Buffer size must not be less then 512 bytes, so we */
  248.       /* can wait for blocksize will be detected by reading */
  249.       if (indput < BLKSIZE) goto put;
  250.       if (pksize < BLKSIZE) pksize = BLKSIZE;
  251. #endif
  252.       pkflush();
  253.    }
  254. put:
  255.    pk_out[indput++] = c;
  256. }
  257.  
  258. int initape(name)
  259. char *name;
  260. {
  261. #ifdef UNIX
  262.    char tn[10]; register char *n;
  263. #endif
  264. #ifdef MSDOS
  265.    register k;
  266. #endif
  267.  
  268.    handle = -1;
  269.  
  270.    pread  = lread  = sread;
  271.    pwrite = lwrite = swrite;
  272.    pback  = lback  = sback;
  273.  
  274.    if (name && name[0]=='-' && name[1]==0) {
  275.       if ((a_flag && !c_flag) || d_flag) {
  276.          (void)fprintf(stderr, "Tar: can\'t update stdout\n");
  277.          return ERRARG;
  278.       }
  279. #ifdef myinp
  280.       if (j_flag
  281. #  ifndef MSDOS
  282.           || w_flag
  283. #  endif
  284.          ) {
  285.          (void)fprintf(stderr, "Tar: input must be free\n");
  286.          return ERRARG;
  287.       }
  288. #endif
  289.       handle = a_flag ? /* stdout */ 1 : /* stdin */ 0;
  290.       myout  = stderr;
  291.    } else {
  292. #ifdef UNIX
  293.       if (name && name[0]) {
  294.          n = name;
  295.       } else {
  296.          n = strcpy(tn, "/dev/mt0"); tn[7] = (ndrive & 7) | '0';
  297.       }
  298.       handle = c_flag ? creat(n, 0666) :
  299.                         open (n, a_flag && !d_flag ? O_RDWR : O_RDONLY);
  300.       if (handle < 0) {
  301.          cantopen(n); return ERINIT;
  302.       }
  303. #endif
  304.  
  305. #ifdef MSDOS
  306.       if (!name || !name[0]) {
  307.          devtype = DEV_FLOP;
  308.      inidisk();
  309.       } else if ((k=qparse(name)) != FALSE) {
  310.          if (k != TRUE) return ERRARG;
  311.          pread   = lread  = qread;
  312.          pwrite  = lwrite = qwrite;
  313.          pback   = lback  = qback;
  314.          devtype = DEV_QIC2;
  315.       } else {
  316.          if (!k_flag && defdev(name)==0) k_flag = TRUE;
  317.          if (k_flag) {
  318.             devtype = DEV_FLOP;
  319.         inidisk();
  320.          } else {
  321.             handle = open(name, !a_flag || d_flag ? O_RDONLY+O_BINARY :
  322.                                  c_flag ? O_CREAT+O_TRUNC+O_WRONLY+O_BINARY :
  323.                                           O_RDWR+O_BINARY,
  324.                                 S_IREAD+S_IWRITE);
  325.             if (handle < 0) {
  326.                cantopen(name); return ERINIT;
  327.             }
  328.             devtype = DEV_FILE;
  329.          }
  330.       }
  331.       if (devtype == DEV_FLOP) {
  332.          pread  = lread  = dread;
  333.          pwrite = lwrite = dwrite;
  334.          pback  = lback  = dback;
  335.       }
  336. #endif
  337.    }
  338.    if (t_flag) {/* yet another redirection */
  339.       rcount = lread; pread = lread = cntread; allblock = 0L;
  340.    }
  341.    if (!cblock & c_flag) printbs(cblock = MAXBLOCK);
  342.    if (handle < 0 || fstat(handle, &sa) != 0) sa.st_mode = S_IFBLK;
  343.    hwrite = handle;
  344.    return CORRECT;
  345. }
  346.  
  347. static void swapbufs __ARGS__((void))
  348. {
  349.    register j; register char *p;
  350.  
  351.    p = pk_inp; pk_inp = io_buf; io_buf = p;
  352.    p = pk_out; pk_out = io_2nd; io_2nd = p;
  353.  
  354.    j = pksize;
  355.    pksize = BLKSIZE*cblock;
  356.    cblock = j/BLKSIZE;
  357. }
  358.  
  359. int runtape()
  360. {
  361. #ifdef MSDOS
  362.    if (devtype == DEV_QIC2) {
  363.       if (qbegin()) return ERINIT;
  364.    }
  365. #endif
  366.    if (pktype == PKpLZW) {
  367.       /* Redirect IO */
  368.       pread  = dpiece;
  369. #ifdef USE_COMPRESS
  370.       pwrite = zwrite;
  371. #else
  372.       pwrite = twofault;
  373. #endif
  374.       pback  = onefault;
  375.  
  376.       swapbufs();
  377.  
  378.       if (x_flag || t_flag || d_flag) {
  379.          register j;
  380.  
  381.          indget = got_length = pksize;
  382.          if ((j=dbegin(getbyte))!=0) {
  383.             if (j < 0) {
  384.                outmem(stderr);
  385.                return ESMALL;
  386.             } else {
  387.                (void)fprintf(stderr,
  388.                   "Tar: archive is not in compresssed format\n");
  389.                return ERINIT;
  390.             }
  391.          }
  392.       }
  393.       if (a_flag || d_flag) {
  394. #ifdef USE_COMPRESS
  395.          if (cbegin(pklevel, putbyte, 0x7fffffffL) != pklevel) {
  396.             outmem(stderr);
  397.             return ESMALL;
  398.          }
  399. #else
  400.          (void)fprintf(stderr,
  401.          "Tar: this restricted version does not support LZW compression\n");
  402.          return ERRARG;
  403. #endif
  404.       }
  405. #ifdef USE_COMPRESS
  406.       indput = 0;
  407. #endif
  408.    } else if (pktype == PKZIP) {
  409.       /* Redirect IO */
  410.       pread = gread; pwrite = gwrite; pback = onefault;
  411.       swapbufs();
  412.  
  413.       if (x_flag || t_flag || d_flag) {
  414.          indget = got_length = pksize;
  415.          if (unzopen(getbyte, ZIP_ANY) != 0) return ziperr();
  416.       }
  417.       indput = 0;
  418.       if (a_flag || d_flag) {
  419.          if (zipcreat(putbyte, ZIP_PKW, pklevel) != 0) return ziperr();
  420.       }
  421.    }
  422.    rblock = mblock = cblock;
  423.    if (c_flag && !mblock) printbs(cblock = mblock = MAXBLOCK);
  424.    wblock = 0;
  425.    n_read = 0;
  426.    return CORRECT;
  427. }
  428.  
  429. void duptape(n)
  430. char *n;
  431. {
  432.    register i;
  433.    static char template[] = "XXXXXX";
  434.  
  435.    io_2nd = getbuf(BLKSIZE * (mblock ? mblock : MAXBLOCK));
  436.    if (!io_2nd) done(ESMALL);
  437.  
  438.    i=strlen(n);
  439.    while (i>0 &&
  440. #ifdef MSDOS
  441.                  n[i-1]!='\\' && n[i-1]!=':' &&
  442. #endif
  443.                                                 n[i-1]!='/') --i;
  444.    scratch = salloc((int)(i + sizeof(template)));
  445.    (void)strncpy(scratch, n, i);
  446.    (void)strcpy (scratch+i, template);
  447.    (void)mktemp (scratch);
  448. #ifdef UNIX
  449.    hwrite = creat(scratch, 0666);
  450. #endif
  451. #ifdef MSDOS
  452.    hwrite = open(scratch, O_CREAT+O_TRUNC+O_RDWR+O_BINARY, S_IREAD+S_IWRITE);
  453. #endif
  454.    if (hwrite < 0) {
  455.       (void)fprintf(myout, "Tar: can\'t create scratch file\n");
  456.       done(EWRITE);
  457.    }
  458. }
  459.  
  460. void backtape()
  461. {
  462.    register i;
  463.  
  464.    talign((long)n_read);
  465.    if ((i = (int)(n_read / BLKSIZE % mblock)) == 0) i = mblock;
  466.    if (!isfile) {
  467.       register j;
  468.  
  469.       if ((*pback)(i)!=i) goto fault;
  470.       if ((j=(*pread)(io_buf, BLKSIZE*rblock))<BLKSIZE) goto fault;
  471.       n_read += j;
  472.    }
  473.    if ((*pback)(i) != i) goto fault;
  474.    wblock = --rblock; indread = indwrite = 0;
  475.    return;
  476. fault:
  477.    (void)fprintf(myout, "Tar: tape seek fault\n");
  478.    done(ERREAD);
  479. }
  480.  
  481. void endtape()
  482. {
  483.    nullblock(steptape());
  484.    if (wblock) {
  485.       if ((*pwrite)(io_2nd, BLKSIZE*((
  486. #ifdef MSDOS
  487.                      devtype == DEV_FILE || devtype == DEV_FLOP
  488. #else
  489.                      isfile
  490. #endif
  491. #ifdef USE_COMPRESS
  492.                      || pwrite == zwrite
  493. #endif
  494.                      || pwrite == gwrite)
  495.                      && wblock < mblock ? wblock : mblock)) < 0) {
  496.          wrerror();
  497.       }
  498.    }
  499. #ifdef USE_COMPRESS
  500.    if (pwrite == zwrite) {/* compression on output */
  501.       if (cflush() < 0) wrerror();
  502.       if (indput > 0) pkflush();
  503.    } else
  504. #endif
  505.    if (pwrite == gwrite) {/* zip compression */
  506.       if (zipclose() == -1L) wrerror();
  507.       if (indput > 0) pkflush();
  508.    }
  509.    if (hwrite >= 0 && close(hwrite)!=0) {
  510.       (void)fprintf(myout, "Tar: tape close error\n");
  511.       done(EWRITE);
  512.    }
  513. }
  514.  
  515. static int readbuf __ARGS__(( void ))
  516. {
  517.    register i;
  518.  
  519.    if (mblock) {
  520.       if ((i=(*pread)(io_buf, BLKSIZE*mblock)) < BLKSIZE || i%BLKSIZE != 0) {
  521.          (void)fprintf(myout, rerror);
  522.          if (i_flag) return -1;
  523.          done(ERREAD);
  524.       }
  525.       n_read += i;
  526.       nblock = i / BLKSIZE;
  527.    } else {
  528.       if ((i = (*pread)(io_buf, MAXBLOCK*BLKSIZE)) < BLKSIZE) {
  529.          (void)fprintf(myout, rerror);
  530.          if (i_flag) return -1;
  531.          done(ERREAD);
  532.       }
  533.       n_read += i;
  534.       talign((long)i);
  535.       mblock = nblock = i / BLKSIZE;
  536.       printbs(cblock = mblock);
  537.    }
  538.    rblock = 0;
  539.    return 0;
  540. }
  541.  
  542. struct header *readtape()
  543. {
  544.    if (rblock>=nblock && readbuf()!=0) return NULL;
  545.    indread = 0;
  546.    return (struct header *)(io_buf + BLKSIZE * rblock++);
  547. }
  548.  
  549. int readbyte()
  550. {
  551.    register c;
  552.  
  553.    if (indread == 0) ++rblock; /* get 1-st byte - take all the block */
  554.    if (rblock>nblock) {
  555.       if (readbuf()!=0) return -1;
  556.       rblock = 1; /* preserve 1-st block from readtape() */
  557.    }
  558.    c = ((unsigned char *)(io_buf + BLKSIZE * (rblock-1)))[indread];
  559.    indread = (indread+1) & (BLKSIZE-1);
  560.    return c;
  561. }
  562.  
  563. void bacouple()
  564. /* return to the beginning of block after try to uncompress */
  565. {
  566.    indread = 0; --rblock;
  567. }
  568.  
  569. int readarch(h, length)
  570. int h; long length;
  571. {
  572.    register i;
  573.  
  574.    while (length > 0) {
  575.       if (rblock>=nblock && readbuf()!=0) return -1;
  576.       if ((i = (nblock-rblock)*BLKSIZE) > length) i = (int)length;
  577.       if (write(h, io_buf + rblock * BLKSIZE, i)!=i)
  578.          extwrerr();
  579.       rblock += (i + BLKSIZE-1) / BLKSIZE;
  580.       length -= i;
  581.    }
  582.    indread = 0;
  583.    return 0;
  584. }
  585.  
  586. struct header *steptape()
  587. {
  588.    if (!mblock) mblock = 1;
  589.    if (wblock >= mblock) {
  590.       if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  591.       wblock = 0;
  592.    }
  593.    indwrite = 0;
  594.    return (struct header *)(io_2nd + BLKSIZE * wblock++);
  595. }
  596.  
  597. void writebyte(c)
  598. int c;
  599. {
  600.    if (indwrite == 0) ++wblock;
  601.    if (wblock > mblock) {
  602.       if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  603.       wblock = 1;
  604.    }
  605.    ((unsigned char *)(io_2nd + BLKSIZE * (wblock-1)))[indwrite] = c;
  606.    indwrite = (indwrite+1) & (BLKSIZE-1);
  607. }
  608.  
  609. int writearch(h, length, name)
  610. int h; long length; char *name;
  611. {
  612.    register i; register j; register k;
  613.    register char *p;
  614.    register b;
  615.  
  616.    if (!mblock) mblock = 1;
  617.  
  618.    b = 0;
  619.    while (length > 0) {
  620.       if (wblock >= mblock) {
  621.          if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  622.          wblock = 0;
  623.       }
  624.       k = BLKSIZE * (mblock-wblock);
  625.       i = length < k ? (int)length : k;
  626.       p = io_2nd + BLKSIZE * wblock;
  627.       if ((j = read(h, p, i)) < 0) {
  628.          (void)fprintf(myout, "Tar: error reading \'%s\'\n", name);
  629.          done(ERREAD);
  630.       }
  631.       /* Calculate number of blocks affected */
  632.       k = (BLKSIZE-1 + j) / BLKSIZE;
  633.       wblock += k;
  634.       b      += k;
  635.       /* Fill the slack area */
  636.       for (p+=j, k=BLKSIZE*k-j; k>0; k--) *p++ = '\0';
  637.       if (j != i) return b;
  638.       length -= i;
  639.    }
  640.    if (wblock >= mblock) {
  641.       if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  642.       wblock = 0;
  643.    }
  644.    indwrite = 0;
  645.    return b;
  646. }
  647.